import os
import pymysql
from pymysql.cursors import DictCursor
from dbutils.pooled_db import PooledDB
from utils.logger import get_logger, error, info, debug
import time

# 创建数据库操作专用的日志器
logger = get_logger("database", daily_rotation=True, level="DEBUG")

# 数据库连接池对象
_pool = None


def init_db_pool(host='139.196.93.182', port=3306, user='root', password='jiankekejian', database='welfare',
               max_connections=10, min_connections=1, charset='utf8mb4'):
    """
    初始化数据库连接池
    
    Args:
        host: 数据库主机地址
        port: 数据库端口
        user: 数据库用户名
        password: 数据库密码
        database: 数据库名称
        max_connections: 最大连接数
        min_connections: 最小连接数
        charset: 字符集
        
    Returns:
        PooledDB: 数据库连接池对象
    """
    global _pool
    try:
        if _pool is None:
            _pool = PooledDB(
                creator=pymysql,  # 使用pymysql作为数据库连接库
                maxconnections=max_connections,  # 连接池允许的最大连接数
                mincached=min_connections,  # 初始化时连接池中至少创建的空闲连接数
                blocking=True,  # 连接池中如果没有可用连接后，是否阻塞等待
                ping=0,  # ping MySQL服务端，检查服务是否可用
                host=host,
                port=port,
                user=user,
                password=password,
                database=database,
                charset=charset,
                cursorclass=DictCursor  # 默认返回字典类型的结果
            )
            logger.info(f"数据库连接池初始化成功，数据库: {database}@{host}:{port}")
        return _pool
    except Exception as e:
        logger.error(f"初始化数据库连接池失败: {str(e)}", exc_info=True)
        raise


def get_connection():
    """
    从连接池获取数据库连接
    
    Returns:
        Connection: 数据库连接对象
    """
    global _pool
    if _pool is None:
        # 如果连接池未初始化，使用默认参数初始化
        init_db_pool()
    try:
        conn = _pool.connection()
        logger.debug("从连接池获取数据库连接成功")
        return conn
    except Exception as e:
        logger.error(f"从连接池获取数据库连接失败: {str(e)}", exc_info=True)
        raise


def execute_query(sql, params=None):
    """
    执行查询SQL语句
    
    Args:
        sql: SQL查询语句
        params: 查询参数，可以是元组、列表或字典
        
    Returns:
        list: 查询结果列表，每个元素为字典
    """
    conn = None
    cursor = None
    start_time = time.time()  # 记录开始时间
    try:
        conn = get_connection()
        cursor = conn.cursor()
        cursor.execute(sql, params)
        result = cursor.fetchall()
        end_time = time.time()  # 记录结束时间
        execution_time = (end_time - start_time) * 1000  # 转换为毫秒
        logger.debug(f"执行查询SQL成功: {sql}, 耗时: {execution_time:.2f}ms")
        return result
    except Exception as e:
        end_time = time.time()  # 记录结束时间
        execution_time = (end_time - start_time) * 1000  # 转换为毫秒
        logger.error(f"执行查询SQL失败: {sql}, 耗时: {execution_time:.2f}ms, 错误: {str(e)}", exc_info=True)
        raise
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def execute_update(sql, params=None):
    """
    执行更新SQL语句（INSERT, UPDATE, DELETE）
    
    Args:
        sql: SQL更新语句
        params: 更新参数，可以是元组、列表或字典
        
    Returns:
        int: 受影响的行数
    """
    conn = None
    cursor = None
    try:
        conn = get_connection()
        cursor = conn.cursor()
        rows = cursor.execute(sql, params)
        conn.commit()
        logger.debug(f"执行更新SQL成功: {sql}, 影响行数: {rows}")
        return rows
    except Exception as e:
        if conn:
            conn.rollback()
        logger.error(f"执行更新SQL失败: {sql}, 错误: {str(e)}", exc_info=True)
        raise
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def execute_many(sql, params_list):
    """
    批量执行SQL语句
    
    Args:
        sql: SQL语句
        params_list: 参数列表，每个元素为一组参数
        
    Returns:
        int: 受影响的行数
    """
    conn = None
    cursor = None
    try:
        conn = get_connection()
        cursor = conn.cursor()
        rows = cursor.executemany(sql, params_list)
        conn.commit()
        logger.debug(f"批量执行SQL成功: {sql}, 影响行数: {rows}")
        return rows
    except Exception as e:
        if conn:
            conn.rollback()
        logger.error(f"批量执行SQL失败: {sql}, 错误: {str(e)}", exc_info=True)
        raise
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def execute_transaction(sql_list, params_list=None):
    """
    在一个事务中执行多条SQL语句
    
    Args:
        sql_list: SQL语句列表
        params_list: 参数列表，与SQL语句列表一一对应
        
    Returns:
        list: 每条SQL语句影响的行数列表
    """
    conn = None
    cursor = None
    try:
        conn = get_connection()
        cursor = conn.cursor()
        # 关闭自动提交
        conn.begin()
        
        results = []
        for i, sql in enumerate(sql_list):
            params = None if params_list is None else params_list[i]
            rows = cursor.execute(sql, params)
            results.append(rows)
        
        conn.commit()
        logger.debug(f"事务执行成功，共执行 {len(sql_list)} 条SQL语句")
        return results
    except Exception as e:
        if conn:
            conn.rollback()
        logger.error(f"事务执行失败，错误: {str(e)}", exc_info=True)
        raise
    finally:
        if cursor:
            cursor.close()
        if conn:
            conn.close()


def close_db_pool():
    """
    关闭数据库连接池
    """
    global _pool
    if _pool is not None:
        # 在DBUtils的PooledDB中没有直接的关闭方法
        # 但我们可以将连接池对象设为None，让Python的垃圾回收机制处理
        _pool = None
        logger.info("数据库连接池已关闭")